#ifndef NETWORKSERVER_H
#define NETWORKSERVER_H

#include "enet/enet.h"

#include "singleton.h"
#include "var.h"
#include "networkNode.h"

namespace sde {

    class NetworkServer : public NetworkNode, public Singleton<NetworkServer> {
    protected:
        void receive(ENetPeer* sender, ENetPacket* packet);
        
        void onConnected(ENetPeer* peer);
        void onDisconnected(ENetPeer* peer);
        
        bool connected;
        
        void receiveInitState(ENetPeer* peer, ENetPacket* packet, int& pos);
        void receiveObjectName(ENetPeer* peer, ENetPacket* packet, int& pos);
        void receiveSetVar(ENetPeer* peer, ENetPacket* packet, int& pos);
        void receiveDestroyObject(ENetPeer* peer, ENetPacket* packet, int& pos);
        void receiveMakeObject(ENetPeer* peer, ENetPacket* packet, int& pos);
        void receiveActionName(ENetPeer* peer, ENetPacket* packet, int& pos);
        void receiveRunAction(ENetPeer* peer, ENetPacket* packet, int& pos);
        void receiveRpc(ENetPeer* peer, ENetPacket* packet, int& pos);
        void receiveRpcResult(ENetPeer* peer, ENetPacket* packet, int& pos);
        void receiveRegisterSetVar(ENetPeer* peer, ENetPacket* packet, int& pos);
        
        std::string doMakeObjectName(std::string desiredName);
        
        std::string resultName;
        
        VarListMap rpcResults;
        
        ENetPeer* server;
        
        typedef std::map<std::string, bool> StringBoolMap;
        
        StringBoolMap registeredSetVars;
        StringBoolMap requestedSetVars;
        
    public:
        NetworkServer();
        
        void connectClient();
        void disconnectClient();
        
        void update(VarMap args);
        
        std::string makeObjectName(std::string desiredName);
        void destroyObject(std::string objectName);
        void setVar(std::string objectName, std::string varName, Var val);
        void distSetVar(std::string objectName, std::string varName, Var val);
        void requestVar(std::string objectName, std::string varName);
        std::string runAction(std::string objectName, std::string actionType, std::string actionName);
        void subscribeRpc(std::string objectName, std::string cmd);
        void requestRpc(std::string objectName, std::string cmd, VarMap args);
        Var finishRpc(std::string objectName, std::string cmd);
    };
    
}

#endif
